package main

import (
	"context"
	"fmt"
	"time"
)

// 什么是Goroutine? 如何让它停止?

// 定义这是一个只读通道，类型为 struct{}。在 Go 中，struct{} 是一个空结构体，通常用于信号传递，因为它不占用任何内存。这个通道用于接收停止信号
func _work1(stopChan <-chan struct{}) {
	for {
		// select 语句用于等待多个通道操作。它会阻塞，直到其中一个 case 可以执行
		select {
		// 当 stopChan 被关闭或者发送了一个值时（在这个例子中是一个空结构体），这个 case 会被执行
		case <-stopChan:
			fmt.Println("stop goroutine")
			return
		default:
			time.Sleep(2 * time.Second)
			fmt.Println("goroutine running...")
		}
	}
}

// 定义了一个名为 worker 的函数，接收一个 context.Context 类型的参数 ctx。这个上下文对象用于控制 Goroutine 的生命周期
func _work2(ctx context.Context) {
	for {
		select {
		// ctx.Done() 返回一个通道，当上下文被取消时，这个通道会被关闭。这里通过 <-ctx.Done() 监听取消信号。如果收到信号，进入这个分支
		case <-ctx.Done():
			fmt.Println("stop goroutine")
			return
		default:
			time.Sleep(2 * time.Second)
			fmt.Println("goroutine running...")
		}
	}
}

//func main() {
//	// _work1
//	//stopChan := make(chan struct{})
//	//go _work1(stopChan)
//	//
//	//time.Sleep(5 * time.Second)
//	//close(stopChan)
//	//
//	//fmt.Println("Main func exiting")
//
//	// _work2
//	// context.Background(): 返回一个空的上下文，作为上下文树的根节点
//	// context.WithCancel: 返回一个新的上下文 ctx 和一个取消函数 cancel。调用 cancel() 会使 ctx.Done() 通道关闭
//	ctx, cancel := context.WithCancel(context.Background())
//	time.Sleep(5 * time.Second)
//	go _work2(ctx)
//	// 调用 cancel() 函数，取消上下文。这会关闭 ctx.Done() 通道，通知 worker Goroutine 退出
//	cancel()
//	time.Sleep(1 * time.Second)
//}
